package com.aiden.app.common.extension

import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.net.Uri
import android.support.annotation.DrawableRes
import android.view.ViewGroup
import android.widget.ImageView
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.Transformation
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.Target
import com.aiden.app.common.R
import com.aiden.app.common.util.LogUtils
import com.aiden.app.common.widget.glide.GlideApp
import com.aiden.app.common.widget.glide.GlideCircleTransform
import com.aiden.app.common.widget.glide.GlideRequest
import com.aiden.app.common.widget.glide.GlideRoundTransform
import jp.wasabeef.glide.transformations.BlurTransformation
import java.io.File

fun ImageView.display(url: String, @DrawableRes placeholder: Int = R.mipmap.default_product, @DrawableRes error: Int = R.mipmap.default_product) {
    get(url).diskCacheStrategy(DiskCacheStrategy.ALL)
            .placeholder(placeholder)
            .error(error)
            .centerCrop()
            .into(this)
}

fun ImageView.display(file: File, @DrawableRes placeholder: Int = R.mipmap.default_product, @DrawableRes error: Int = R.mipmap.default_product) {
    get(file).diskCacheStrategy(DiskCacheStrategy.ALL)
            .placeholder(placeholder)
            .error(error)
            .into(this)
}

fun ImageView.display(@DrawableRes drawResId: Int, @DrawableRes placeholder: Int = R.mipmap.default_product, @DrawableRes error: Int = R.mipmap.default_product) {
    get(drawResId).diskCacheStrategy(DiskCacheStrategy.ALL)
            .placeholder(placeholder)
            .error(error)
            .into(this)
}

fun ImageView.display(uri: Uri, @DrawableRes placeholder: Int = R.mipmap.default_product, @DrawableRes error: Int = R.mipmap.default_product) {
    get(uri).diskCacheStrategy(DiskCacheStrategy.ALL)
            .placeholder(placeholder)
            .error(error)
            .into(this)
}

fun ImageView.display(any: Any?, @DrawableRes placeholder: Int = R.mipmap.default_product, @DrawableRes error: Int = R.mipmap.default_product) {
    get(any).diskCacheStrategy(DiskCacheStrategy.ALL)
            .placeholder(placeholder)
            .error(error)
            .into(this)
}

fun ImageView.fitCenterImage(url: String, @DrawableRes placeholder: Int = R.mipmap.default_product, @DrawableRes error: Int = R.mipmap.default_product) {
    get(url).fitCenter().diskCacheStrategy(DiskCacheStrategy.RESOURCE)
            .placeholder(placeholder)
            .error(error)
            .into(this)
}

fun ImageView.displayBanner(url: String) {
    get(url).diskCacheStrategy(DiskCacheStrategy.ALL)
            .placeholder(R.mipmap.default_banner)
            .error(R.mipmap.default_banner)
            .into(this)
}

fun ImageView.displayRound(url: String, @DrawableRes placeholder: Int = R.mipmap.default_product, @DrawableRes error: Int = R.mipmap.default_product, radius: Float = 10F) {
    get(url).diskCacheStrategy(DiskCacheStrategy.ALL)
            .placeholder(placeholder)
            .error(error)
            .transform(GlideRoundTransform(context, radius))
            .into(this)
}

fun ImageView.displayRoundPx6(url: String, @DrawableRes placeholder: Int = R.mipmap.default_product, @DrawableRes error: Int = R.mipmap.default_product) {
    get(url).diskCacheStrategy(DiskCacheStrategy.ALL)
            .dontAnimate()
            .placeholder(placeholder)
            .error(error)
            .transform(GlideRoundTransform(context, 6f))
            .into(this)
}

fun ImageView.displayRound(url: Any, @DrawableRes placeholder: Int = R.mipmap.default_product, @DrawableRes error: Int = R.mipmap.default_product, radius: Float = 10F) {
    get(url).diskCacheStrategy(DiskCacheStrategy.ALL)
            .placeholder(placeholder)
            .error(error)
            .centerCrop()
            .transform(GlideRoundTransform(context, radius))
            .into(this)
}

fun ImageView.displayRound(bitmap: Bitmap, @DrawableRes placeholder: Int = R.mipmap.default_product, @DrawableRes error: Int = R.mipmap.default_product, radius: Float = 10f) {
    val options = RequestOptions().centerInside()
    get(bitmap).apply(options)
            .diskCacheStrategy(DiskCacheStrategy.ALL)
            .placeholder(placeholder)
            .error(error)
            .transform(GlideRoundTransform(context, radius))
            .into(this)
}

fun ImageView.displayRound(uri: Uri, @DrawableRes placeholder: Int = R.mipmap.default_product, @DrawableRes error: Int = R.mipmap.default_product, radius: Float = 10f) {
    get(uri).diskCacheStrategy(DiskCacheStrategy.ALL)
            .placeholder(placeholder)
            .error(error)
            .transform(GlideRoundTransform(context, radius))
            .into(this)
}

fun ImageView.displayCircle(url: String, @DrawableRes placeholder: Int = R.mipmap.default_product, @DrawableRes error: Int = R.mipmap.default_product) {
    val options = RequestOptions().circleCrop()
    get(url).diskCacheStrategy(DiskCacheStrategy.ALL)
            .dontAnimate()
            .placeholder(placeholder)
            .transform(GlideCircleTransform(context))
//            .skipMemoryCache(false)
            .error(error)
            .into(this)
}

fun ImageView.displayCircle(@DrawableRes drawResId: Int, @DrawableRes placeholder: Int = R.mipmap.default_product, @DrawableRes error: Int = R.mipmap.default_product) {
    val options = RequestOptions().circleCrop()
    get(drawResId).apply(options)
            .diskCacheStrategy(DiskCacheStrategy.ALL)
            .placeholder(placeholder)
            .transform(GlideCircleTransform(context))
            .error(error)
            .into(this)
}

fun ImageView.displayCircle(bitmap: Bitmap, @DrawableRes placeholder: Int = R.mipmap.default_product, @DrawableRes error: Int = R.mipmap.default_product) {

    val options = RequestOptions().circleCrop()
    get(bitmap).apply(options)
            .diskCacheStrategy(DiskCacheStrategy.ALL)
            .placeholder(placeholder)
            .transform(GlideCircleTransform(context))
            .error(error)
            .into(this)
}

fun ImageView.displayDontTransform(url: String, @DrawableRes placeholder: Int = R.mipmap.default_product, @DrawableRes error: Int = R.mipmap.default_product) {
    get(url).diskCacheStrategy(DiskCacheStrategy.ALL)
            .dontTransform()
            .placeholder(placeholder)
            .error(error)
            .into(this)
}

fun ImageView.displayBlur(url: String, @DrawableRes placeholder: Int = R.mipmap.default_banner, @DrawableRes error: Int = R.mipmap.default_banner) {
    get(url).diskCacheStrategy(DiskCacheStrategy.ALL)
            .transform(BlurTransformation(25, 5))
            .placeholder(placeholder)
            .error(error)
            .into(this)
}

fun ImageView.displayHead(url: String) {
    displayCircle(url, placeholder = R.mipmap.icon_default_head, error = R.mipmap.icon_default_head)
}

fun ImageView.displayReal(url: String, @DrawableRes placeholder: Int = R.mipmap.default_product, @DrawableRes error: Int = R.mipmap.default_product, radius: Float = context?.dp2px(5)?.toFloat()!!) {
    get(url).diskCacheStrategy(DiskCacheStrategy.ALL)
            .dontTransform()
            .placeholder(placeholder)
            .error(error)
//            .transform(GlideRoundTransform(context, radius))
            .listener(object : RequestListener<Drawable> {
                override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean {
                    return false
                }

                override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
                    resource?.let {
                        val width = it.intrinsicWidth
                        val height = it.intrinsicHeight

                        val radio = width.toFloat() / height.toFloat()

                        val lp = this@displayReal.layoutParams as ViewGroup.LayoutParams
                        LogUtils.e("Glide", "ImageView width=${lp.width}, height=${lp.height}")
                        lp.height = Math.floor((lp.width / radio + 0.5)).toInt()
                        this@displayReal.layoutParams = lp

                        LogUtils.e("Glide", "Image width=$width, height=$height, radio=$radio, changeWidth=${lp.width}, changeHeight=${lp.height}")
                    }

                    return false
                }

            })
            .into(this)
}

fun ImageView.get(file: File): GlideRequest<Drawable> = GlideApp.with(context).load(file).dontAnimate()

fun ImageView.get(@DrawableRes drawResId: Int): GlideRequest<Drawable> = GlideApp.with(context).load(drawResId).dontAnimate()

fun ImageView.get(uri: Uri): GlideRequest<Drawable> = GlideApp.with(context).load(uri).dontAnimate()

fun ImageView.get(bitmap: Bitmap): GlideRequest<Drawable> = GlideApp.with(context).load(bitmap).dontAnimate()

fun ImageView.get(any: Any?): GlideRequest<Drawable> = GlideApp.with(context).load(any).dontAnimate()

class GlideWrapper {
    var url: String? = null
    var imageView: ImageView? = null
    var placeholder: Int = R.mipmap.default_product
    var error: Int = R.mipmap.default_product
    var transform: Transformation<Bitmap>? = null
}

fun ImageView.load(init: GlideWrapper.() -> Unit) {
    val wrap = GlideWrapper()
    wrap.init()
    execute(wrap)
}

private fun execute(wrapper: GlideWrapper) {
    wrapper.imageView?.let {
        var request = it.get(wrapper.url).placeholder(wrapper.placeholder).error(wrapper.error);
        if (wrapper.transform != null) {
            request.transform(wrapper.transform!!)
        }
        request.into(it)
    }
}